package com.ww.common;

import com.alibaba.fastjson.JSONObject;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;


/**
 * @author nan
 * @name ServiceResponse
 * @description 微服务Controller通用接口返回对象
 * 泛型中可以放任意类型对象例如：
 * 业务实体类、各种Exception对象、集合对象
 * @date 2018/9/28
 */
public class ServiceResponse<T> implements Serializable {

    /**
     * 业务上是否成功
     */
    private boolean success;

    /**
     * 返回消息描述信息（可以是文字描述，错误描述；也可能是异常堆栈信息字符串）
     */
    private String message;

    /**
     * 业务处理状态码
     */
    private String code;

    private T data;

    private Date searchTime;

    public ServiceResponse() {

    }

    @SuppressWarnings("unchecked")
    private ServiceResponse(Date searchTime, boolean success, String code, String message, T data) {
        this.searchTime = searchTime;
        this.success = success;
        this.code = code;
        this.message = message;
        this.data = data;
        // 处理失败，但未指定错误码，设置默认错误码
        if (!success && code == null) {
            this.code = "201";
        }
        // 处理成功，但未指定code，设置默认code
        if (success && code == null) {
            this.code = "200";
        }
        // 数据对象为空时，自动补充空map
        if (data == null) {
            this.data = (T) new HashMap<String, String>();
        }
        if (message == null)
            this.message = "";
    }

    /**
     * 创建接口成功对象
     *
     * @param message -返回消息
     * @param data    -业务实体对象
     * @return ServiceResponse
     * 结果样例：
     * <pre>
     *     {
     *         success: true,
     *         code: "0000",
     *         message: "成功处理10条数据",
     *         data: {
     *             id: "001"
     *         }
     *     }
     * </pre>
     */
    public static <T> ServiceResponse<T> success(String message, T data) {
        return new ServiceResponse<>(new Date(), true, "200", message, data);
    }

    /**
     * 创建接口成功对象
     *
     * @param data -业务实体对象
     * @return ServiceResponse
     * 结果样例：
     * <pre>
     *      {
     *         success: true,
     *         code: "0000",
     *         message: "",
     *         data: {
     *             id: "001"
     *         }
     *     }
     * </pre>
     */
    public static <T> ServiceResponse<T> success(T data) {
        return success(null, data);
    }

    /**
     * 创建接口成功对象
     *
     * @return ServiceResponse
     * * 结果样例：
     * <pre>
     *      {
     *         success: true,
     *         code: "0000",
     *         message: "",
     *         data: {}
     *     }
     * </pre>
     */
    public static <T> ServiceResponse<T> success() {
        return success(null);
    }

    /**
     * 创建接口失败对象
     *
     * @param code    - 错误码
     * @param message -返回消息
     * @return ServiceResponse
     * <pre>
     *      {
     *         success: false,
     *         code: "200",
     *         message: "调用第三方接口失败",
     *         data: {}
     *     }
     * </pre>
     */
    public static <T> ServiceResponse<T> error(String code, String message) {
        return new ServiceResponse<>(new Date(), false, code, message, null);
    }

    /**
     * 创建接口失败对象
     *
     * @param message -返回消息
     * @return ServiceResponse
     * <pre>
     *      {
     *         success: false,
     *         code: "6666",
     *         message: "调用第三方接口失败",
     *         data: {}
     *     }
     * </pre>
     */
    public static <T> ServiceResponse<T> error(String message) {
        return error("6666", message);
    }

    /**
     * 创建接口失败对象
     *
     * @param ex -返回消息
     * @return ServiceResponse
     * <pre>
     *      {
     *         success: false,
     *         code: "600",
     *         message: "java.lang.NullPointerException: ..........",
     *         data: {
     *
     *         }
     *     }
     * </pre>
     */
    public static <T> ServiceResponse<T> error(Exception ex) {
        return error("600", ex.toString());
    }

    @Override
    public String toString() {
        return JSONObject.toJSONString(this);
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Date getSearchTime() {
        return searchTime;
    }

    public void setSearchTime(Date searchTime) {
        this.searchTime = searchTime;
    }
}
